
#include <iostream>
#include <functional>
#include <cstdarg>
using namespace std;

char fun(char c)
{
    return c + 1;
}

void callback_test1()
{
    char (*call)(char) = fun;
    cout << "callback1:" << call('a') << endl;
}

void callback_test2()
{
    typedef char (*CallBack)(char);
    CallBack call = fun;
    cout << "callback2:" << call('a') << endl;
}

void callback_test3()
{
    using CallBack = char (*)(char);
    CallBack call = fun;
    cout << "callback3:" << call('a') << endl;
}

void callback_test4()
{
    using CallBack = function<char(char)>;
    CallBack call = fun;
    cout << "callback4:" << call('a') << endl;
}

int sum1(int count, ...)
{
    if (count <= 0)
    {
        return 0;
    }
    /*
    为了实现可变参数列表，首先需要声明一个va_list类型的指针
    va_list类型是在cstdarg头文件里面定义的，该指针用来依次
    指向各个参数
    va_start是一个宏，用来初始化arg_ptr，使其指向列表的第一个
    参数，这个宏的第二个参数是sum函数参数列表省略号前得固定参
    数的名称，用来确定第一个参数的位置
    */
    va_list arg_ptr;
    va_start(arg_ptr, count);
    int CountSum = 0;
    // va_arg是一个宏，返回arg_ptr指向的参数位置，并使arg_ptr递增来指向下一个参数值
    // va_arg宏的第二个参数是需要统计的第一个参数的类型，如果类型不正确，程序也可能会执行，但得到的是无用的数据，arg_ptr将被错误地递增
    for (int i = 0; i < count; ++i)
    {
        CountSum += va_arg(arg_ptr, int);
    }
    // 将va_list类型的指针复位成空值
    va_end(arg_ptr);
    return CountSum;
}
template <typename T>
T return_max(T val1, T val2)
{
    return val1 > val2 ? val1 : val2;
}
int main()
{
    callback_test1();
    callback_test2();
    callback_test3();
    callback_test4();

    // 带有可变参数的回调
    int (*call)(int, ...) = sum1;
    cout << "带有可变参数的回调:" << call(3, 5, 6, 1) << endl;

    // 带有模板函数的回调
    function<int(int, int)> fun = return_max<int>;
    cout << "带有模板函数的回调:" << fun(4, 9) << endl;
    return 0;
}